Before we get started working on our final project.
I think it's very important for us to completely understand how replication works and when you should
use the weight for child function in your local scripts.
You should already have a pretty decent understanding of replication.
Basically, when a player joins a game, they download their own copy of the game like all the part
scripts and other players, and the server tells the players to adjust the properties of those instances
when needed.
This way, a player's copy of the game stays separate from the server's copy, and any changes the player
makes on their copy of the game does not affect the server's copy.
As an example, we're going to see replication in action here with this client and server setup.
Here I have in studio now to see incoming and outgoing data.
We can go into the view tab and go down to the stats section and enable the network UI.
And we can do this for both the client and the server.
So now here on the server, I can go ahead and see all the data that is being sent out.
And here on the client, I could go ahead and see all the data that I am receiving.
So currently we're at 0.15kB per second and outgoing from the server again is 0.015.
Now, if I were to create a new part on the server here and let me just go and place one like right
here.
We did send out a little bit more data to tell the player to create a new part on their copy of the
game.
So here in my copy of the game, there's this new part here.
And then when the server starts to move this part, it's going to tell this player to start moving it
on their copy of the game as well.
So as I start to move the part, you can see that the outgoing data is increasing.
And then if you look at the client as well, our overall incoming data has also been increased.
Now because this part is unanchored, my player currently has network ownership over it.
Or basically my computer is calculating the physics for this part.
And because I have network ownership, I can move this part and it will replicate to the server.
So if I start moving the part, as you can see now, I'm sending data out from my computer and the server
is receiving some data as well.
So again, as I continue to move it, you can see that the data in the out physics section has increased
and the server is getting more data coming into it.
Now that means if I want to go and anchor the part on the server.
So let me go to the model tab parts and then let me anchor this part.
That means I have disabled physics on the part.
And now my player here doesn't have a network ownership over this part anymore.
So if I start to move it, as you can see, I'm only moving it on my copy of the game.
I'm not sending out any data for physics, and the server doesn't see that I'm moving it at all.
However, if the server starts moving, it's going to tell my player to update it to this new position
that the server moved it to.
So if I move it like over here, there you can see it replicated to my copy of the game.
And again, because my copy is separate from the server's, anything I do here does not replicate to
the server, nor does it replicate to other players in the game.
It's only affecting my copy of the game.
So the only exception of things that are replicated from my game to the server and the server broadcasts,
that replication to other players would be the movement of my character and any other parts that I have
network ownership of.
Other than that, anything else I change in my game, such as changing the color of these houses, making
one fly up in the sky, or anything of that kind of nature.
It's not going to be replicated to the server or other players.
It's only going to happen on my game.
Okay, so now that we have a pretty good understanding of replication, let's go ahead and take a dive
into specifically when you should use wait for child and when you should not use wait for child.
So as you already know, the wait for child function allows a local script to yield until an instance
has been replicated to their copy of the game.
This prevents us from causing errors in our scripts.
When we try to directly index or access an instance that hasn't been replicated yet.
However, there is a lot of confusion surrounding wait for child and when you're supposed to use it.
Now, when a player joins a game, there's going to be an event that gets fired once a snapshot of the
game has been fully replicated to our side of the game.
So this is inside of game, which is the data model for our whole game.
And this event is called loaded and it fires on the client when the game finishes loading for the first
time.
What does it mean when it finishes loading.
Well, that means we receive a snapshot of the entire game.
So all the contents of the workspace replicated storage things and like the sound service and all of
these other sections, we get the snapshot of the game and we replicate it.
And then once those items have been fully replicated, then this loaded event fires.
Now any local scripts that you have within these starter sections like the starter pack, starter player,
starter guy, things of that nature, they are not going to execute until our game has been loaded.
So any instances that you have saved inside of studio that are a part of your game will be inside of
that snapshot, and they'll be immediately accessible to your local scripts that are inside of your
different starter containers.
Now, these instances are known as static, and you do not need to worry about waiting for them to replicate.
And because you don't need to worry about them having to replicate, that means you do not need to use
wait for child on static instances.
However, there are other instances that will be generated during the runtime of our game, like a player's
character, maybe instances created by server scripts, instances copied to the workspace from like
server storage and so on.
And all of those are known as dynamic instances.
So again, anything created during the runtime of your game is going to be a dynamic instance.
These instances are basically placed in a queue to be replicated to you.
You can't rely on them existing when your scripts run, so you have to use wait for trial on dynamic
instances.
So for example, if I had a guy within our starter guy, let's say I had a screen guy in here with some
different stuff in it, like frames and whatnot.
If I had a script inside of starter player scripts that wanted to access this guy when it is placed
inside of our player guy folder, then because it's cloned, the only thing I would need to wait for
is the screen guy itself.
The starter guy service has already been loaded by the time the script will run, and that means all
I need to wait for is when the screen guy gets cloned into our player guy folder, and I don't need
to wait for any of the other descendants.
This is because cloning is known as a synchronous operation, or basically all of the descendants from
the root, which would be this guy are going to be immediately available once the root has been cloned
and replicated to our copy of the game.
So if I ever wanted to access my local player and get our player guy folder, I would have to wait for
this particular screen guy.
And then once I've waited for the screen guy, I no longer need to wait for any of the other descendants
of the screen guy so I can access the frame freely without having to worry about it not existing.
I also don't need to wait for the player guy folder either, because it's guaranteed to be non-nil when
you index the local player.
Now, if I had a local script within the screen guy, well, that makes it even easier because I can
just reference the guy itself using script dot parent, and because again, the script is only going
to run when it's been loaded and this guy has been copied to our player guy.
I don't need to wait for any of the descendants either, so I can access script Dot parent and get things
like the frame.
I don't need to wait for any of it.
It's already been replicated and they are static instances.
All right, so let me go ahead and summarize this for you.
Any local scripts that exist within the starter containers, like starter player scripts or the starter
guy, they do not need to use wait for child on static instances.
And a static instance is all the instances that exist within the snapshot of the game that is downloaded
by a player when they join the game.
However, any local scripts that are going to be inside of something like replicated first are going
to have to use wait for child, because if they try to access any instances outside of replicated first,
there's no guarantee that those instances have been replicated yet.
You're also going to have to use weight for child on dynamic instances, or any instances that are added
during the runtime of the game.
If a player reset and a new character was added to that player, well, you're going to have to use
weight for child because that's a dynamic instance.
Did the server just add some new instances into the game?
Well, you got to wait for those as well because that's a dynamic instance.
So let's go ahead and take a look at this diagram about replication.
So as you can see right here this is when our player connects to the game.
And when our player connects into the game.
Then we get a snapshot of everything that's going to be inside of replicated first.
And that begins to load.
And then once replicated first is finished loading any scripts that are inside of replicated first begin
to run.
That means if you had a script inside of replicated first, and you had some other stuff in here, like
a part when the script runs, I don't need to wait for this part that's already inside of replicated.
First, it's a static instance, so I could just do game Dot replicated first and immediately access
this part without having to use wait for child.
However, because the script is running before our game loads anything outside of replicated.
First you must use wait for child on.
So if I wanted to access something in the workspace from this local script and replicated first, for
some reason I will have to use wait for child.
I cannot directly index anything in the workspace because there's no guarantee that it will exist when
the script runs.
So as proof, what I'm going to do is I'm actually going to print the number of descendants that are
in the workspace.
So we can just do workspace, get descendants.
And then I'm going to do the exact same thing here within our starter player script, I'm going to print
the number of descendants in the workspace.
So basically this script right here should print like one, because the only thing that will be loaded
is likely going to be the terrain.
And then this one should print all of the stuff that exists within the workspace, because the script
will only run once the game has been loaded.
So if we go ahead and play test the game.
We're going to go ahead.
See?
Look it printed one and then our other script printed 161,606 instances within the workspace.
So as you can see that script that's in replicated first, none of those assets, like all of these
houses that I made, have been replicated to the client yet.
So you have to use wait for child when you access anything outside of replicated first in a local script.
However, because my other script was inside of a starter player container, it wasn't going to run
until the first snapshot that was given to me has been replicated.
So that means inside of that script in my starter player scripts, I can go ahead and freely access
any of these houses without worrying about them not being replicated.
Now, I'm also going to show you something a little bit interesting.
I'm going to wait three seconds and then after those three seconds, I'm going to print the workspace,
get descendants again, and then inside a replicated.
First I'm going to do the same thing, but I'm only going to wait something like 0.1 seconds and we're
going to print the workspace, get descendants again.
So we should be able to see how many instances had loaded inside of our workspace after 0.1 seconds
has elapsed.
So if we hit play, our game is loading and we should see one get printed.
There we go.
We got one.
Then we got 161,606 and actually replicated first printed that as well.
So maybe 18.1 seconds is actually a little too short.
So what I could do is let me wait even a shorter period of time.
Because the server has been run on my computer, the latency between the server and the client is basically
zero, so everything loads super fast.
But there we go.
You see, first it printed one and then we waited 0.001 seconds and then it printed 21,049 objects.
So not everything in the workspace had been loaded yet.
Then the local script that was inside of starter player printed 161,606.
And then you're going to see, wait, why did the number increase if everything had already been loaded
in our game, why did more things load?
Well, all those additional instances were actually part of our player model.
So as you know, our player model doesn't exist in that snapshot that gets replicated to our computer.
Our player's character is a dynamic instance.
So that means we had to wait for it to get replicated to our copy of the game and spawned in.
And as you can see, all of these different instances in here had to be replicated.
So our player's character would be known as a dynamic instance, which is why it didn't print originally
when that local script ran.
So what do we learn from all of this?
Well, any local scripts that are inside of replicated first can safely access instances inside of replicated
first.
But those scripts must use wait for child on instances outside of replicated first.
So if my script wanted to access any instance like in the workspace lighting sound service, it must
use wait for child any local script that are inside of the starter containers like starter, player,
scripts, starter, GUI and so on.
They will execute after the game has been loaded so they are able to freely access static instances
in the game services like the workspace, replicated storage and other services.
However, they must use wait for child on dynamic instances like the player's character guy is copied
to the player's player guy folder, instances created by a server, scripts during runtime, and stuff
like that.
Hopefully this lecture helped to clear up any confusion on replication and wait for child.
And we're going to begin to apply this knowledge about replication in our final project.
Thanks for listening.